using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Controls;
using Microsoft.VisualStudio.TeamFoundation.WorkItemTracking;

namespace WitCustomControls
{
	public partial class WorkItemIdReference : UserControl, IWorkItemControl
	{
		public WorkItemIdReference()
		{
			InitializeComponent();
			((IWorkItemControl)this).InvalidateDatasource();
		}

		private void AddEventHandler()
		{
			if (m_workItem != null && m_workItem.Id != 0 && m_workItem.State == "Closed")
			{
				m_workItem.FieldChanged += new WorkItemFieldChangeEventHandler(this.workItem_FieldChanged);
			}
		}

		private void workItem_FieldChanged(object sender, WorkItemEventArgs e)
		{
			//Test to see if the user is reactivating a work item
			if (!this.IsDisposed && e.Field != null && e.Field.Name == "State" && e.Field.OriginalValue.ToString() == "Closed" && e.Field.Value.ToString() != "Closed")
			{
				WorkItem parentWorkItem = m_workItem.Store.GetWorkItem((int)m_workItem.Fields[m_fieldName].Value);
				if (parentWorkItem.State == "Closed")
				{
					MessageBox.Show("Work Items cannot be changed from a Closed State if parent Work Items are still closed.", "Hierarchy error");

					System.Threading.Thread resetThread = new System.Threading.Thread(new System.Threading.ThreadStart(ResetState));
					resetThread.Start();
				}
			}
		}

		private void ResetState()
		{
			m_workItem.State = "Closed";
			m_workItem.Fields["Assigned To"].Value = string.Empty;
		}

		private void buttonModify_Click(object sender, EventArgs e)
		{
			if (m_fieldIsValid && m_workItem.Fields[m_fieldName].IsEditable)
			{
				// Open up WorkItemPicker dialog
				WorkItemPicker wiPicker = new WorkItemPicker(m_workItem.Store, m_workItem);
				if (wiPicker.ShowDialog(this) == DialogResult.OK)
				{
					int workItemId = wiPicker.WorkItemId;
					OnBeforeUpdateDatasource(EventArgs.Empty);

					m_workItem.Fields[m_fieldName].Value = ((workItemId == 0) ? (int?)null : wiPicker.WorkItemId);

					((IWorkItemControl)this).InvalidateDatasource();
				}
			}
		}

		private void labelId_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			if (m_fieldIsValid)
			{
				object o = m_workItem.Fields[m_fieldName].Value;
				if (o != null && o is int)
				{
					// Use ServiceProvider to get documentservice and open work item
					DocumentService ds = (DocumentService)m_serviceProvider.GetService(typeof(DocumentService));
					IWorkItemDocument doc = ds.GetWorkItem(m_workItem.Store.TeamFoundationServer, (int)o, this);
					try
					{
						ds.ShowWorkItem(doc);
					}
					finally
					{
						doc.Release(this);
					}
				}
			}
		}

		#region IWorkItemControl Members

		private EventHandlerList m_events;

		private EventHandlerList Events
		{
			get
			{
				if (m_events == null)
				{
					m_events = new EventHandlerList();
				}
				return m_events;
			}
		}

		private static object EventBeforeUpdateDatasource = new object();
		private static object EventAfterUpdateDatasource = new object();
		event EventHandler IWorkItemControl.BeforeUpdateDatasource
		{
			add
			{
				Events.AddHandler(EventBeforeUpdateDatasource, value);
			}
			remove
			{
				Events.RemoveHandler(EventBeforeUpdateDatasource, value);
			}
		}
		event EventHandler IWorkItemControl.AfterUpdateDatasource
		{
			add
			{
				Events.AddHandler(EventAfterUpdateDatasource, value);
			}
			remove
			{
				Events.RemoveHandler(EventAfterUpdateDatasource, value);
			}
		}

		protected virtual void OnBeforeUpdateDatasource(EventArgs eventArgs)
		{
			EventHandler handler = (EventHandler)Events[EventBeforeUpdateDatasource];
			if (handler != null)
			{
				handler.Invoke(this, eventArgs);
			}
		}

		protected virtual void OnAfterUpdateDatasource(EventArgs eventArgs)
		{
			EventHandler handler = (EventHandler)Events[EventAfterUpdateDatasource];
			if (handler != null)
			{
				handler.Invoke(this, eventArgs);
			}
		}

		void IWorkItemControl.Clear()
		{
			labelId.Text = string.Empty;
		}

		void IWorkItemControl.FlushToDatasource()
		{
			// nothing to do
		}

		void IWorkItemControl.InvalidateDatasource()
		{
			m_fieldIsValid = (m_workItem != null &&
					!string.IsNullOrEmpty(m_fieldName) &&
					m_workItem.Fields.Contains(m_fieldName));
			labelId.Text = "______";
			if (m_fieldIsValid)
			{
				object val = m_workItem.Fields[m_fieldName].Value;
				if (val != null)
				{
					labelId.Text = string.Format("{0}", m_workItem.Fields[m_fieldName].Value);
				}
			}
		}

		private StringDictionary m_properties;
		StringDictionary IWorkItemControl.Properties
		{
			get
			{
				return m_properties;
			}
			set
			{
				m_properties = value;
			}
		}

		private bool m_readOnly;
		bool IWorkItemControl.ReadOnly
		{
			get
			{
				return m_readOnly;
			}
			set
			{
				m_readOnly = value;
			}
		}

		private IServiceProvider m_serviceProvider;
		void IWorkItemControl.SetSite(IServiceProvider serviceProvider)
		{
			m_serviceProvider = serviceProvider;
		}

		private WorkItem m_workItem;
		object IWorkItemControl.WorkItemDatasource
		{
			get
			{
				return m_workItem;
			}
			set
			{
				m_workItem = (WorkItem)value;

				if (m_workItem != null && m_workItem.Fields[m_fieldName] != null)
				{
					this.buttonModify.Enabled = m_workItem.Fields[m_fieldName].IsEditable;
				}
				AddEventHandler();
			}
		}

		private string m_fieldName;
		string IWorkItemControl.WorkItemFieldName
		{
			get
			{
				return m_fieldName;
			}
			set
			{
				m_fieldName = value;
			}
		}

		#endregion

		private bool m_isDirty;
		public bool IsDirty
		{
			get
			{
				return m_isDirty;
			}
			set
			{
				m_isDirty = value;
			}
		}

		private bool m_fieldIsValid = false;

	}
}